package com.spzx.payment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.payment.config.AlipayConfig;
import com.spzx.payment.domain.PaymentInfo;
import com.spzx.payment.service.AlipayService;
import com.spzx.payment.service.PaymentInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: atguigu
 * @create: 2025-05-10 15:14
 */
@Slf4j
@Service
public class AlipayServiceImpl implements AlipayService {

    @Autowired
    private PaymentInfoService paymentInfoService;

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 对接支付宝返回支付表单用于H5端支付
     *
     * @param orderNo
     * @return
     */
    @Override
    public String submitAlipay(String orderNo) {
        try {
            //1.保存本地交易记录
            PaymentInfo paymentInfo = paymentInfoService.savePaymentInfo(orderNo);
            if (!"0".equals(paymentInfo.getPaymentStatus())) {
                throw new ServiceException("本地交易记录支付状态有误");
            }
            //2.对接支付宝服务端，产生一笔支付宝交易，获取支付宝支付表单
            // 创建请求对象
            AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
            // 同步回调 应用引导用户去到成功页面
            alipayRequest.setReturnUrl(AlipayConfig.return_payment_url);
            // 异步回调 用户付款成功后，支付宝异步通知商户系统
            alipayRequest.setNotifyUrl(AlipayConfig.notify_payment_url);

            /******必传参数******/
            JSONObject bizContent = new JSONObject();
            //商户订单号，商家自定义，保持唯一性
            bizContent.put("out_trade_no", paymentInfo.getOrderNo());
            //支付金额，最小值0.01元
            //bizContent.put("total_amount", paymentInfo.getAmount());
            bizContent.put("total_amount", paymentInfo.getAmount());
            //订单标题，不可使用特殊符号
            bizContent.put("subject", paymentInfo.getContent());
            /******可选参数******/
            //手机网站支付默认传值QUICK_WAP_WAY
            bizContent.put("product_code", "QUICK_WAP_WAY");
            alipayRequest.setBizContent(bizContent.toString());
            AlipayTradeWapPayResponse response =
                    alipayClient.pageExecute(alipayRequest, "POST");
            return response.getBody(); //调用SDK生成表单;
        } catch (AlipayApiException e) {
            log.error("支付宝支付异常:{}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 支付宝回调:用户付款成功后，支付宝会通知商户系统支付结果
     *
     * @param paramMap
     * @return
     */
    @Override
    public String paySuccessNotify(Map<String, String> paramMap) {
        try {
            //1.验证签名 避免出现虚假通知 ，确保该接口调用方是支付宝/防止数据被篡改
            log.info("支付宝支付成功回调参数:{}", paramMap);
            boolean flag = AlipaySignature.rsaCheckV1(
                    paramMap,
                    AlipayConfig.alipay_public_key,
                    AlipayConfig.charset,
                    AlipayConfig.sign_type
            );
            if (!flag) {
                log.error("支付宝支付成功回调:签名验证失败");
                return "failure";
            }
            //2.基于通知ID进行幂等性处理
            String notifyId = paramMap.get("notify_id");
            String key = "pay:alipay:notifyId:" + notifyId;
            Boolean onece = redisTemplate.opsForValue().setIfAbsent(key, notifyId, 25, TimeUnit.HOURS);
            if (onece) {
                try {
                    //3.验证金额、支付状态 -- 确保用户付款成功
                    String tradeStatus = paramMap.get("trade_status");
                    if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                        //4.更新本地交易记录状态：已支付
                        paymentInfoService.updatePaymentStatus(paramMap);
                        return "success";
                    }
                } catch (Exception e) {
                    redisTemplate.delete(key);
                    throw new RuntimeException(e);
                }
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
        return null;
    }
}
